const fs = require("fs");
const path = require("path");
const axios = require("axios");
const FormData = require("form-data");
const { now } = require("moment");
const fileInfo = {
  count: 0,
  max: 0,
  size: 0
};
const start = now();
let defaultConfig = {
  baseURL: "", // process.env.VUE_APP_BASE_URL
  deleteURL: "/upload.php?action=delete",
  uploadURL: "/upload.php",
  dir: "dist"
};
let maxLength = 0

// 第一步读取文件夹内的文件
// 第二步删除文件，再调用上传文件方法
// 第三步 上传文件

/**
 * 删除和上传的2个api
 * @returns {AxiosPromise<any>}
 */
const deleteFileApi = () => axios.get(`${defaultConfig.baseURL}${defaultConfig.deleteURL}`, {});
const uploadFileApi = params => {
  const form = new FormData();
  form.append("file", fs.createReadStream(params.path));
  form.append("action", "upload");
  form.append("directory", params.directory);
  return axios.post(`${defaultConfig.baseURL}${defaultConfig.uploadURL}`, form, { headers: form.getHeaders() });
};

/**
 * 读取文件夹内的文件
 *
 * @param folderPath
 * @returns {string[]|*[]}
 */
function readFolder(folderPath) {
  console.log(folderPath);
  folderPath = folderPath.replace(/\\/g, "/");
  if (fs.existsSync(folderPath)) {
    return fs.readdirSync(folderPath).map(fileName => {
      return path.join(folderPath, fileName);
    });
  } else {
    console.log("文件夹不存在");
    return [];
  }
}

/**
 * 读取文件夹内的所有文件
 *
 * @returns {*[]}
 */
function getAllFile(dir) {
  if (!dir) {
    console.error("dir不能为空 ");
    return [];
  }
  const stack = readFolder(path.join(__dirname, `../${dir}`));
  const result = [];
  while (stack.length > 0) {
    const lastStact = stack.pop().replace(/\\/g, "/");
    const stats = fs.statSync(lastStact); // 读取文件属性
    if (stats.isDirectory()) { // 是文件夹就读取文件夹的内容
      const children = readFolder(lastStact);
      children.map(item => {
        stack.push(item);
      });
    } else if (stats.isFile()) { // 是文件就存储结果， 是连接符号就不要
      fileInfo.count += 1;
      fileInfo.size += stats.size;
      const name = lastStact.slice(lastStact.lastIndexOf("/") + 1);
      const dirPath = lastStact.split(dir);
      if (stats.size > fileInfo.max) {
        fileInfo.max = stats.size;
        fileInfo.maxFileName = name;
      }
      const directory = dirPath[1].slice(1, dirPath[1].lastIndexOf("/"))
      const length = directory.length > 0 ? (directory + name).length + 1 : name.length
      if( length > maxLength) {
        maxLength = length
      }
      result.push({
        name: name,
        path: lastStact,
        size: stats.size,
        directory
      });
    }
  }
  return result;
}

/**
 * 格式化
 *
 * @param size
 * @returns {string}
 */
function formatSize(size) {
  if (size > 1024 * 1024) {
    return Math.round(size * 100 / 1024 / 1024) / 100 + "MB";
  } else if (size > 1024) {
    return Math.round(size * 100 / 1024) / 100 + "KB";
  }
  return size + "Byte";
}

/**
 * 上传文件时限制了并发上传数量（20个文件）
 * 主要是在PHP下并发数量过大容易崩溃
 *
 * @param files
 */
function uploadFile(files) {
  const all = [];
  let n = 0;
  while (files.length > 0 && n < 20) {
    const last = files.pop();
    n++;
    const req = uploadFileApi(last).then(res => {
      const d = res.data
      console.log(fill(d.data, maxLength + 4) + fill(d.size + '', 11) + "上传成功")
    }).catch(error => {
      console.log(error);
    });
    all.push(req);
  }
  Promise.all(all).then(() => {
    if (files.length === 0) {
      const end = now();
      console.log("全部上传完成");
      const max = formatSize(fileInfo.max);
      console.log(`最大文件: ${fileInfo.maxFileName}    ${max}`);
      console.log(`总文件数: ${fileInfo.count}`);
      const size = formatSize(fileInfo.size);
      console.log(`总内存大小: ${size}`);
      const time = end - start;
      console.log(`用时: ${time}毫秒`);
    } else {
      uploadFile(files);
    }
  });
}

/**
 * 先删除已有文件， 再上传
 *
 * @param config
 */
// eslint-disable-next-line no-undef
exports.upload = (config = {}) => {
  defaultConfig = { ...defaultConfig, ...config };
  if (!defaultConfig.baseURL) {
    console.error("baseUrl 不能为空");
    return;
  }
  if (!defaultConfig.dir) {
    console.error("dir 不能为空");
    return;
  }
  console.log(defaultConfig);
  deleteFileApi()
    .then(res => {
      console.log(`状态码: ${res.status}`, res.data);
      if (res.status === 200) {
        console.log("删除完成");
        if (res.data.status) {
          console.log("删除成功");
          const files = getAllFile(defaultConfig.dir);
          const start = fill("====开始上传", maxLength + 28, "=")
          console.log(start)
          uploadFile(files);
        } else {
          console.log("删除失败");
        }
      }
    }).catch(error => {
    console.error(error);
  });
};

function fill(str, length, world = ' ') {
  while (str.length < length) {
    str = str + world
  }
  return str;
}
